package ecom.shell.commandsImpl;

import ecom.beans.exception.DeviseException;
import ecom.shell.exception.InsuffisantPrivilegeException;
import ecom.beans.EcomAdminRemote;
import ecom.beans.EcomCustomerRemote;
import ecom.beans.ProductstoreBean;
import ecom.shell.commandsImpl.OutputCommandImpl.Outputs;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import shell.ShellCommand;
import shell.ShellContext;

public class ProductstoreCommandImpl implements ShellCommand {

    private ShellContext _context = null;

    public ProductstoreCommandImpl(ShellContext context) {
        _context = context;
    }

    @Override
    public String getName() {
        return "productstore";
    }

    @Override
    public String getUsage() {
        return "productstore";
    }

    @Override
    public String getShortDescription() {
        String description = "Productstore commands\n";
        description += "\t-help ....................................................................get productstore commands description\n";
        if (true == _context.getVar("isAdmin")) {
            description += "\t-add [name] [city] [account ID]...........................................create a new productstore\n";
            description += "\t-remove [store ID]........................................................delete a productstore\n";
        }
        description += "\t-id [productstore ID]............................................................display specified store details\n";
        return description;
    }

    @Override
    public String execute(String cmdline, PrintStream out, PrintStream err) throws InsuffisantPrivilegeException {
        StringBuilder res = new StringBuilder();
        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        EcomAdminRemote ecomAdminBean = (EcomAdminRemote) _context.getVar("adminBean");
        Outputs currentOutput = (Outputs) _context.getVar("output");
        String currentCurrency = (String) _context.getVar("currency");

        Set<ProductstoreBean> storeList = null;

        StringTokenizer st = new StringTokenizer(cmdline, " ");

        st.nextToken();

        if (st.countTokens() == 0) {
            storeList = ecomAdminBean.getAllStores(null);
            try {
                return printList(out, storeList, currentOutput, ecomCustomerBean, currentCurrency);
            } catch (Exception ex) {
                System.err.println("Error with getting all productstores : " + ex.getMessage());
            }
        } else {
            String option = st.nextToken();

            if (option.equals("-help")) {
                res.append(getShortDescription());
            } else if (option.equals("-add")) {
                if (true != _context.getVar("isAdmin")) {
                    throw new InsuffisantPrivilegeException();
                }
                if (st.countTokens() == 3) {
                    try {
                        String name = st.nextToken();
                        String adress = st.nextToken();
                        String postalCode = st.nextToken();
                        String city = st.nextToken();
                        String tel = st.nextToken();
                        String iban = st.nextToken();
                        Long id = ecomAdminBean.createProductStore(name, adress, postalCode, city, tel, iban, new Double(0));
                        res.append("Producttore created with id :").append(id);
                    } catch (Exception ex) {
                        err.println("Error with productstore creation : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-remove")) {
                if (true != _context.getVar("isAdmin")) {
                    throw new InsuffisantPrivilegeException();
                }
                if (st.countTokens() == 1) {
                    try {
                        Long id = Long.valueOf(st.nextToken());
                        ecomAdminBean.removeProductstore(id);
                        res.append("Productstore id : ").append(id).append(" deleted");
                    } catch (Exception ex) {
                        res.append(ex.toString());
                        err.println("Error with productstore remove" + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-id")) {
                if (st.countTokens() == 1) {
                    try {
                        Long id = Long.valueOf(st.nextToken());
                        ProductstoreBean store = ecomCustomerBean.getProductstoreById(id);
                        return printStore(out, store, currentOutput, ecomCustomerBean, currentCurrency);
                    } catch (Exception ex) {
                        err.println("Error with productstore detail : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else {
                err.println(option + " is not known for productstore command");
            }
        }
        return res.toString();
    }

    private String printList(PrintStream out, Set<ProductstoreBean> productstore, Outputs currentOutput, EcomCustomerRemote ecomCustomerBean, String currentCurrency) throws DeviseException, IOException {
        StringBuilder res = new StringBuilder();
        if (currentOutput.equals(Outputs.XML)) {
            Element productstoreE = new Element("stores");
            org.jdom.Document document = new Document(productstoreE);
            for (ProductstoreBean store : productstore) {
                productstoreE.addContent(buildXMLStoreNode(store, true, ecomCustomerBean, currentCurrency));
            }
            XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
            return sortie.outputString(document);
        } else if (currentOutput.equals(Outputs.TEXT)) {
            for (ProductstoreBean store : productstore) {
                res.append(printTEXT(out, store, currentCurrency)).append("\n");
            }
        } 
        else {
            res.append("Output format '").append(currentOutput).append("' is not implementing for this command");
        }
        return res.toString();
    }

    private String printStore(PrintStream out, ProductstoreBean store, Outputs currentOutput, EcomCustomerRemote ecomCustomerBean, String currentCurrency) throws DeviseException, IOException {
        Set<ProductstoreBean> productstore = new HashSet<ProductstoreBean>();
        productstore.add(store);
        return printList(out, productstore, currentOutput, ecomCustomerBean, currentCurrency);
    }

    private String printTEXT(PrintStream out, ProductstoreBean store, String currentCurrency) {
        return (store.toString() + " IN " + currentCurrency);
    }

    public static Element buildXMLStoreNode(ProductstoreBean productstore, boolean withAccount, EcomCustomerRemote ecomCustomerBean, String currentCurrency) throws DeviseException {
        Element store = new Element("productstore");
        Attribute id = new Attribute("id", String.valueOf(productstore.getIdProductStore()));
        store.setAttribute(id);

        Element name = new Element("name");
        name.setText(productstore.getName());
        store.addContent(name);

        Element city = new Element("city");
        city.setText(productstore.getCity());
        store.addContent(city);

        if (withAccount) {
            Element account = new Element("account");
            Attribute accountId = new Attribute("id", String.valueOf(productstore.getIban().getIban()));
            account.setAttribute(accountId);
            store.addContent(account);

            Element balance = new Element("balance");
            DecimalFormat myFormatter = new DecimalFormat("##0.00");
            balance.setText(myFormatter.format(ecomCustomerBean.convertFromEuro(productstore.getIban().getBalance(), currentCurrency)));
            Attribute currency = new Attribute("currency", currentCurrency);
            balance.setAttribute(currency);
            account.addContent(balance);
        }
        return store;
    }

  
}
